package com.luom.springbootinit.service.impl;

import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.luom.springbootinit.common.ErrorCode;
import com.luom.springbootinit.constant.CommonConstant;
import com.luom.springbootinit.exception.BusinessException;
import com.luom.springbootinit.exception.ThrowUtils;
import com.luom.springbootinit.mapper.BorrowRecordMapper;
import com.luom.springbootinit.model.dto.borrowRecord.BorrowRecordAddRequest;
import com.luom.springbootinit.model.dto.borrowRecord.BorrowRecordQueryRequest;
import com.luom.springbootinit.model.dto.borrowRecord.BorrowRecordUpdateRequest;
import com.luom.springbootinit.model.entity.Book;
import com.luom.springbootinit.model.entity.BorrowRecord;
import com.luom.springbootinit.model.entity.Category;
import com.luom.springbootinit.model.entity.User;
import com.luom.springbootinit.model.enums.BrStatusEnum;
import com.luom.springbootinit.model.vo.BorrowRecordVO;
import com.luom.springbootinit.service.BookService;
import com.luom.springbootinit.service.BorrowRecordService;
import com.luom.springbootinit.service.CategoryService;
import com.luom.springbootinit.service.UserService;
import com.luom.springbootinit.utils.SqlUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 借阅信息服务实现
 */
@Service
@Slf4j
public class BorrowRecordServiceImpl extends ServiceImpl<BorrowRecordMapper, BorrowRecord> implements BorrowRecordService {

    @Resource
    private UserService userService;

    @Resource
    private BookService bookService;

    @Resource
    private CategoryService categoryService;

    @Resource
    private BorrowRecordMapper borrowRecordMapper;

    /**
     * 校验数据
     *
     * @param borrowRecord
     * @param add          对创建的数据进行校验
     */
    @Override
    public void validBorrowRecord(BorrowRecord borrowRecord, boolean add) {

        ThrowUtils.throwIf(borrowRecord == null, ErrorCode.PARAMS_ERROR);
        // 从对象中取值
        Integer userId = borrowRecord.getUserId();
        Integer bookId = borrowRecord.getBookId();
        String brStatus = borrowRecord.getBrStatus();
        // 创建数据时，参数不能为空
        if (add) {
            // 校验规则
            if (bookId == null) {
                throw new BusinessException(ErrorCode.PARAMS_ERROR, "书籍id不能为空");
            } else if (bookId < 0) {
                throw new BusinessException(ErrorCode.PARAMS_ERROR, "书籍id不能小于0");
            }
        }
        // 修改数据时，有参数则校验
        // 校验规则
        if (StringUtils.isNotBlank(brStatus)) {
            ThrowUtils.throwIf(brStatus.length() > 50, ErrorCode.PARAMS_ERROR, "订单状态错误");
            // 使用 getEnumByValue 方法检查输入状态是否有效
            BrStatusEnum statusEnum = BrStatusEnum.getEnumByValue(brStatus);
            ThrowUtils.throwIf(statusEnum == null, ErrorCode.PARAMS_ERROR, "输入的订单状态错误");
        }
    }

    /**
     * 获取查询条件
     *
     * @param borrowRecordQueryRequest
     * @return
     */
    @Override
    public QueryWrapper<BorrowRecord> getQueryWrapper(BorrowRecordQueryRequest borrowRecordQueryRequest) {

        QueryWrapper<BorrowRecord> queryWrapper = new QueryWrapper<>();
        if (borrowRecordQueryRequest == null) {
            return queryWrapper;
        }
        // 从对象中取值
        Integer id = borrowRecordQueryRequest.getId();
        String brStatus = borrowRecordQueryRequest.getBrStatus();
        String sortField = borrowRecordQueryRequest.getSortField();
        String sortOrder = borrowRecordQueryRequest.getSortOrder();

        // 补充需要的查询条件
        // 模糊查询

        // 精确查询
        queryWrapper.eq(ObjectUtils.isNotEmpty(id), "id", id);
        queryWrapper.eq(StringUtils.isNotBlank(brStatus), "brStatus", brStatus);

        if (CollectionUtils.isNotEmpty(borrowRecordQueryRequest.getUserIdList())) {
            queryWrapper.in("userId", borrowRecordQueryRequest.getUserIdList());
        }
        if (CollectionUtils.isNotEmpty(borrowRecordQueryRequest.getBookIdList())) {
            queryWrapper.in("bookId", borrowRecordQueryRequest.getBookIdList());
        }
        // 排序规则
        queryWrapper.orderBy(SqlUtils.validSortField(sortField),
                sortOrder.equals(CommonConstant.SORT_ORDER_ASC),
                sortField);
        return queryWrapper;
    }

    /**
     * 获取借阅信息封装
     *
     * @param borrowRecord
     * @param request
     * @return
     */
    @Override
    public BorrowRecordVO getBorrowRecordVO(BorrowRecord borrowRecord, HttpServletRequest request) {
        // 对象转封装类
        if (borrowRecord == null) {
            return null;
        }
        BorrowRecordVO borrowRecordVO = new BorrowRecordVO();
        BeanUtils.copyProperties(borrowRecord, borrowRecordVO);

        // 1. 关联查询用户信息
        Integer userId = borrowRecord.getUserId();
        if (userId != null && userId > 0) {
            User user = userService.getById(userId);
            if (user != null) {
                borrowRecordVO.setUserId(user.getId());
                borrowRecordVO.setUserAccount(user.getUserAccount());
                borrowRecordVO.setUserName(user.getUserName());
                borrowRecordVO.setEmail(user.getEmail());
                borrowRecordVO.setPhone(user.getPhone());
                borrowRecordVO.setUserAvatar(user.getUserAvatar());
                borrowRecordVO.setUserProfile(user.getUserProfile());
                borrowRecordVO.setUserRole(user.getUserRole());
            }
        }

        // 2. 关联查询图书信息
        Integer bookId = borrowRecord.getBookId();
        if (bookId != null && bookId > 0) {
            Book book = bookService.getById(bookId);
            if (book != null) {
                borrowRecordVO.setBookId(book.getId());
                borrowRecordVO.setTitle(book.getTitle());
                borrowRecordVO.setAuthor(book.getAuthor());
                borrowRecordVO.setPublisher(book.getPublisher());
                borrowRecordVO.setPublishDate(book.getPublishDate());
                borrowRecordVO.setPrice(book.getPrice());
                borrowRecordVO.setCategoryId(book.getCategoryId());

                // 3. 关联查询所属分类（已内联）
                Integer categoryId = book.getCategoryId();
                if (categoryId != null && categoryId > 0) {
                    Category category = categoryService.getById(categoryId);
                    if (category != null) {
                        borrowRecordVO.setCategoryName(category.getName());
                    }
                }
            }
        }
        return borrowRecordVO;
    }

    /**
     * 分页获取借阅信息封装
     *
     * @param borrowRecordPage
     * @param request
     * @return
     */
    @Override
    public Page<BorrowRecordVO> getBorrowRecordVOPage(Page<BorrowRecord> borrowRecordPage, HttpServletRequest request) {
        List<BorrowRecord> borrowRecordList = borrowRecordPage.getRecords();
        Page<BorrowRecordVO> borrowRecordVOPage = new Page<>(borrowRecordPage.getCurrent(), borrowRecordPage.getSize(), borrowRecordPage.getTotal());
        if (CollUtil.isEmpty(borrowRecordList)) {
            return borrowRecordVOPage;
        }
        // 对象列表 => 封装对象列表
        List<BorrowRecordVO> borrowRecordVOList = borrowRecordList.stream()
                .map(borrowRecord -> getBorrowRecordVO(borrowRecord, request))
                .collect(Collectors.toList());

        borrowRecordVOPage.setRecords(borrowRecordVOList);
        return borrowRecordVOPage;
    }

    @Override
    public boolean updateRecord(BorrowRecordUpdateRequest borrowRecordUpdateRequest) {
        BorrowRecord borrowRecord = new BorrowRecord();
        BeanUtils.copyProperties(borrowRecordUpdateRequest, borrowRecord);
        // 数据校验
        validBorrowRecord(borrowRecord, false);
        // 判断是否存在
        long id = borrowRecord.getId();
        BorrowRecord oldBorrowRecord = getById(id);
        ThrowUtils.throwIf(oldBorrowRecord == null, ErrorCode.NOT_FOUND_ERROR);
        if ("returned".equals(borrowRecord.getBrStatus())) {
            UpdateWrapper<Book> updateWrapper = new UpdateWrapper<>();
            updateWrapper.eq("id", oldBorrowRecord.getBookId()).setSql("inventory = inventory + 1");
            boolean update = bookService.update(updateWrapper);
            ThrowUtils.throwIf(!update, ErrorCode.OPERATION_ERROR);
        } else if ("borrowed".equals(borrowRecord.getBrStatus())) {
            UpdateWrapper<Book> updateWrapper = new UpdateWrapper<>();
            updateWrapper.eq("id", oldBorrowRecord.getBookId()).setSql("inventory = inventory - 1");
            boolean update = bookService.update(updateWrapper);
            ThrowUtils.throwIf(!update, ErrorCode.OPERATION_ERROR);
        }
        // 操作数据库
        boolean result = updateById(borrowRecord);
        ThrowUtils.throwIf(!result, ErrorCode.OPERATION_ERROR);
        return true;
    }

    @Override
    public BorrowRecordQueryRequest addQueryParams(BorrowRecordQueryRequest borrowRecordQueryRequest) {
        String userAccount = borrowRecordQueryRequest.getUserAccount();
        String userName = borrowRecordQueryRequest.getUserName();
        String email = borrowRecordQueryRequest.getEmail();
        String phone = borrowRecordQueryRequest.getPhone();
        String title = borrowRecordQueryRequest.getTitle();
        //查询用户id
        List<User> userList = userService.query()
                .select("id")
                .like(ObjectUtils.isNotEmpty(userName), "userName", userName)
                .like(ObjectUtils.isNotEmpty(userAccount), "userAccount", userAccount)
                .like(ObjectUtils.isNotEmpty(email), "email", email)
                .like(ObjectUtils.isNotEmpty(phone), "phone", phone)
                .list();
        if (ObjectUtils.isNotEmpty(userList)) {
            List<Integer> userIds = userList.stream().map(User::getId).collect(Collectors.toList());
            borrowRecordQueryRequest.setUserIdList(userIds);
        }
        //查询图书id
        List<Book> bookList = bookService.query()
                .select("id")
                .like(ObjectUtils.isNotEmpty(title), "title", title)
                .list();
        if (ObjectUtils.isNotEmpty(bookList)) {
            List<Integer> bookIds = bookList.stream().map(Book::getId).collect(Collectors.toList());
            borrowRecordQueryRequest.setBookIdList(bookIds);
        }
        return borrowRecordQueryRequest;
    }

    @Override
    public PageInfo<BorrowRecordVO> getBorrowRecordVOPage(boolean isMyRecord , BorrowRecordQueryRequest borrowRecordQueryRequest, HttpServletRequest request) {
        int current = borrowRecordQueryRequest.getCurrent();
        int pageSize = borrowRecordQueryRequest.getPageSize();
        String sortField = borrowRecordQueryRequest.getSortField();
        String sortOrder = borrowRecordQueryRequest.getSortOrder();

        // 添加查询用户id
        if (isMyRecord){
            User loginUser = userService.getLoginUser(request);
            borrowRecordQueryRequest.setUserId(loginUser.getId());
        }

        // 排序查询
        if (StringUtils.isNotBlank(sortField) && StringUtils.isNotBlank(sortOrder)) {
            sortOrder = SqlUtils.getValidSortOrder(sortOrder);
            PageHelper.startPage(current, pageSize, sortField + " " + sortOrder);
        } else {
            PageHelper.startPage(current, pageSize);
        }

        List<BorrowRecordVO> recordVOList = borrowRecordMapper.getPage(borrowRecordQueryRequest);

        return new PageInfo<>(recordVOList);
    }

    @Override
    public int updateBatchStatus(List<Integer> ids) {
        return borrowRecordMapper.updateBatchById(ids);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public long addBorrowRecord(BorrowRecordAddRequest borrowRecordAddRequest, HttpServletRequest request) {

        // 将实体类和 DTO 进行转换
        BorrowRecord borrowRecord = new BorrowRecord();
        BeanUtils.copyProperties(borrowRecordAddRequest, borrowRecord);
        // 数据校验
        this.validBorrowRecord(borrowRecord, true);
        // 获取登录用户
        User loginUser = userService.getLoginUser(request);
        User user = userService.getById(loginUser.getId());
        if (user.getEmail() == null && user.getPhone() == null)
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "请先填写邮箱或手机号");
        // 查询是否借书并且未归还
        List<BorrowRecord> borrowRecords = query()
                .eq("userId", user.getId())
                .ne("brStatus", "returned")
                .eq("bookId", borrowRecord.getBookId())
                .list();
        ThrowUtils.throwIf(!borrowRecords.isEmpty(), ErrorCode.OPERATION_ERROR, "您已借阅过该书籍，请先归还");
        // 设置用户 id
        borrowRecord.setUserId(user.getId());
        // 判断库存
        Integer bookInventory = bookService.getById(borrowRecord.getBookId()).getInventory();
        ThrowUtils.throwIf(bookInventory <= 0, ErrorCode.OPERATION_ERROR, "图书余量不足");
        // 修改数据库--图书库存减一
        boolean update = bookService.updateBookInventory(borrowRecord.getBookId(), false);
        ThrowUtils.throwIf(!update, ErrorCode.OPERATION_ERROR);
        // 写入数据库
        boolean result = save(borrowRecord);
        ThrowUtils.throwIf(!result, ErrorCode.OPERATION_ERROR);
        // 返回新写入的数据 id
        return (long) borrowRecord.getId();
    }
}
